import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  WebView,
  Image,
  ListView,
  TouchableHighlight,
  Navigator,
  Switch,
  Dimensions,
} from 'react-native';

import {
    Container, Header, Content, Button, Title, Icon, List, ListItem,
    Spinner,
} from 'native-base';

import Styles from './Styles';
import {Copper, CoapMessage} from './Copper';
import SocketUtil from './SocketUtil';

require('./static/jscolor.js.html');

export default class LightControl extends Component {
    WEBVIEW_REF = 'WEBVIEW_REF';
    URI_COLOR_LIGHT_COLOR = '/colorLightColor';
    URI_COLOR_LIGHT_STATE = '/colorLightState';
    URI_WHITE_LIGHT_STATE = '/whiteLightState';
    URI_SWITCH_STATE = '/switchState';

    TOKEN_SET_COLOR_LIGHT_COLOR = 'STCLC';
    TOKEN_SET_COLOR_LIGHT_STATE = 'STCLS';
    TOKEN_SET_WHITE_LIGHT_STATE = 'STWLS';
    TOKEN_SET_SWITCH_STATE = 'STSWS';

    TOKEN_GET_COLOR_LIGHT_COLOR = 'GTCLC';
    TOKEN_GET_COLOR_LIGHT_STATE = 'GTCLS';
    TOKEN_GET_WHITE_LIGHT_STATE = 'GTWLS';
    TOKEN_GET_SWITCH_STATE = 'GTSWS';

    state = {
      colorLightOn: true,
      whiteLightOn: false,
      switchOn: false,
      colorString: "",
    };


    socketUtil = new SocketUtil();

    constructor(props) {
        super(props);
        this.socketUtil.initSocket(this.onMessage.bind(this), () => {
            this.getSwitchState(this.URI_COLOR_LIGHT_STATE);
            this.getSwitchState(this.URI_WHITE_LIGHT_STATE);
            this.getSwitchState(this.URI_SWITCH_STATE);
        });
        this.messageQueue = [];
        this.intervalCount = 0;
        this.msgId = 0;
    }

    render() {
        const view =
        <View style={Styles.container}>
            <Header>
                <Button transparent onPress={() => this.props.navigator.pop()}><Icon name='ios-arrow-back'/></Button>
                <Title>{this.props.route.title}</Title>
            </Header>
            <View style={{flex: 1}}>

                    <WebView
                      ref={this.WEBVIEW_REF}
                      automaticallyAdjustContentInsets={false}
                      style={{borderWidth:1}}
                      source={{uri: 'file:///android_asset/static/LightColor.html'}}
                      onNavigationStateChange={this.onNavigationStateChange.bind(this)}
                      javaScriptEnabled={true}
                      domStorageEnabled={true}
                      startInLoadingState={false}
                    />

            </View>
            <List>
                <ListItem>
                    <View style={{flexDirection:'row', justifyContent:'space-between'}}>
                        <Text>Color light</Text>
                        <Switch
                          onValueChange={(value) => {
                              this.setState({colorLightOn: value});
                              this.setSwitchState(this.URI_COLOR_LIGHT_STATE, value);
                          }}
                          value={this.state.colorLightOn} />
                      </View>
                </ListItem>
                <ListItem>
                    <View style={{flexDirection:'row', justifyContent:'space-between'}}>
                        <Text>White light</Text>
                        <Switch
                          onValueChange={(value) => {
                              this.setState({whiteLightOn: value});
                              this.setSwitchState(this.URI_WHITE_LIGHT_STATE, value);
                          }}
                          value={this.state.whiteLightOn} />
                      </View>
                </ListItem>
                <ListItem>
                    <View style={{flexDirection:'row', justifyContent:'space-between'}}>
                        <Text>Switch</Text>
                        <Switch
                          onValueChange={(value) => {
                              this.setState({switchOn: value});
                              this.setSwitchState(this.URI_SWITCH_STATE, value);
                          }}
                          value={this.state.switchOn} />
                      </View>
                </ListItem>
            </List>
        </View>;

        return view;
    }

    componentDidMount()
    {
        this.refs[this.WEBVIEW_REF].reload();

        // Interval for delay message packets sent to 100ms
        this.sendPacketInterval = setInterval(() => {
            let msg = this.messageQueue.shift();
            if(msg != undefined) {
                this.socketUtil.send(this.props.route.light.IP, Copper.DEFAULT_PORT, msg);
            }
        }, 100);

        // Interval for sync states with device every 5s
        this.stateInterval = setInterval(() => {
            // this.getSwitchState(this.URI_COLOR_LIGHT_STATE);
            // this.getSwitchState(this.URI_WHITE_LIGHT_STATE);
            // this.getSwitchState(this.URI_SWITCH_STATE);
        }, 5000);
    }

    componentWillUnmount() {
        clearInterval(this.sendPacketInterval);
        clearInterval(this.stateInterval);
        if(this.setLightColorInterval != undefined) {
            clearInterval(this.setLightColorInterval);
        }
        this.socketUtil.close();
    }

    onNavigationStateChange(navState) {
        let colorString = navState.title;
        console.log(colorString);
        if(colorString.startsWith("RGB:")) {
            this.setLightColor(colorString);
        }
    }

    getLightColor() {
        let msg = new CoapMessage(Copper.MSG_TYPE_CON, Copper.GET);
        msg.setUri("127.0.0.1", this.URI_COLOR_LIGHT_COLOR);
        msg.setUriPort(Copper.DEFAULT_PORT);
        msg.setToken(this.getTokenForUri(this.URI_COLOR_LIGHT_COLOR, false));
        let packet = Copper.serialize(msg);
        this.socketUtil.send(this.props.route.light.IP, Copper.DEFAULT_PORT, packet);
    }

    setLightColor(colorString) {
        if(this.state.colorString === colorString) {
            return;
        }

        // Cancel previous message send timer
        if(this.setLightColorInterval != undefined) {
            clearInterval(this.setLightColorInterval);
        }

        this.setState({colorString});
        let msg = new CoapMessage(Copper.MSG_TYPE_CON, Copper.PUT);
        msg.setUri("127.0.0.1", this.URI_COLOR_LIGHT_COLOR);
        msg.setUriPort(Copper.DEFAULT_PORT);
        msg.setToken(this.getTokenForUri(this.URI_COLOR_LIGHT_COLOR, true));
        msg.setPayload(colorString);
        let msgId = this.getNextMessageId();
        msg.setMID(msgId);
        let packet = Copper.serialize(msg);

        this.setLightColorRsp = false;
        this.setLightColorPacket = packet;
        this.setLightColorMsgId = msgId;
        this.setLightColorRetries = 0;
        this.setLightColorInterval = setInterval(() => {
            if(this.setLightColorRsp == false) {
                this.setLightColorRetries++;
                if(this.setLightColorRetries > 5) {
                    console.log("cancel set color interval. msgId:", msgId);
                    clearInterval(this.setLightColorInterval);
                    this.setLightColorInterval = undefined;
                }
                else {
                    console.log("resend msgid:", msgId);
                    this.socketUtil.send(this.props.route.light.IP, Copper.DEFAULT_PORT, this.setLightColorPacket);
                }
            }
        }, 800);

        this.socketUtil.send(this.props.route.light.IP, Copper.DEFAULT_PORT, packet);
    }

    getSwitchState(switchStateUri) {
        let msg = new CoapMessage(Copper.MSG_TYPE_CON, Copper.GET);
        msg.setUri("127.0.0.1", switchStateUri);
        msg.setUriPort(Copper.DEFAULT_PORT);
        msg.setToken(this.getTokenForUri(switchStateUri, false));
        let packet = Copper.serialize(msg);
        this.sendPacket(packet);
    }

    setSwitchState(switchStateUri, onOff) {
        let msg = new CoapMessage(Copper.MSG_TYPE_CON, Copper.PUT);
        msg.setUri("127.0.0.1", switchStateUri);
        msg.setUriPort(Copper.DEFAULT_PORT);
        msg.setToken(this.getTokenForUri(switchStateUri, true));
        msg.setPayload(onOff ? "1" : "0");
        let packet = Copper.serialize(msg);
        this.socketUtil.send(this.props.route.light.IP, Copper.DEFAULT_PORT, packet);
    }

    onMessage(msg, rinfo){
        console.log('recevied: ' + msg.length);
        var data = Array.from(msg);
        let coapMsg = Copper.parse(data);
        console.log(coapMsg.getSummary());
        let token = coapMsg.getToken();
        let payload = coapMsg.getPayload();
        let msgId = coapMsg.getMID();

        console.log("token: ", token);
        if(token === this.TOKEN_GET_COLOR_LIGHT_STATE) {
            this.setState({colorLightOn: payload != undefined && payload[0] == '1'.charCodeAt()});
        }
        else if(token === this.TOKEN_GET_WHITE_LIGHT_STATE) {
            this.setState({whiteLightOn: payload != undefined && payload[0] == '1'.charCodeAt()});
        }
        else if(token === this.TOKEN_GET_SWITCH_STATE) {
            this.setState({switchOn: payload != undefined && payload[0] == '1'.charCodeAt()});
        }
        else if(token == this.TOKEN_SET_COLOR_LIGHT_COLOR) {
            console.log('msgId:', msgId);
            console.log('this.setLightColorMsgId', this.setLightColorMsgId);
            if(msgId == this.setLightColorMsgId) {
                console.log("Set color rsp recevied.");
                clearInterval(this.setLightColorInterval);

                this.setLightColorRsp = true;
                this.setLightColorPacket = undefined;
                this.setLightColorInterval = undefined;
            }
        }
    }

    getTokenForUri(uri, set) {
        if(set) {
            if(uri === this.URI_COLOR_LIGHT_COLOR) {
                return this.TOKEN_SET_COLOR_LIGHT_COLOR;
            }
            else if(uri === this.URI_COLOR_LIGHT_STATE) {
                this.gotColorLightState = true;
                return this.TOKEN_SET_COLOR_LIGHT_STATE;
            }
            else if(uri === this.URI_WHITE_LIGHT_STATE) {
                this.gotWhiteLightState = true;
                return this.TOKEN_SET_WHITE_LIGHT_STATE;
            }
            else if(uri === this.URI_SWITCH_STATE) {
                this.gotSwitchState = true;
                return this.TOKEN_SET_SWITCH_STATE;
            }
        }
        else {
            if(uri === this.URI_COLOR_LIGHT_COLOR) {
                return this.TOKEN_GET_COLOR_LIGHT_COLOR;
            }
            else if(uri === this.URI_COLOR_LIGHT_STATE) {
                return this.TOKEN_GET_COLOR_LIGHT_STATE;
            }
            else if(uri === this.URI_WHITE_LIGHT_STATE) {
                return this.TOKEN_GET_WHITE_LIGHT_STATE;
            }
            else if(uri === this.URI_SWITCH_STATE) {
                return this.TOKEN_GET_SWITCH_STATE;
            }
        }

        return '';
    }

    sendPacket(packet) {
        this.messageQueue.push(packet);
    }

    getNextMessageId() {
        this.msgId++;
        return this.msgId;
    }

}
